package com.gjxx.netty;

import com.gjxx.common.tcp.*;
import com.gjxx.netty.codec.*;
import com.gjxx.netty.req.TerminalCommonMsg;
import com.gjxx.netty.req.TerminalRegisterMsg;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
public class MyDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        String HEXES = "0123456789ABCDEF";
        byte[] req = new byte[msg.readableBytes()];
        msg.readBytes(req);

        final StringBuilder hex = new StringBuilder(2 * req.length);
        for (int i = 0; i < req.length; i++) {
            byte b = req[i];
            hex.append(HEXES.charAt((b & 0xF0) >> 4))
                    .append(HEXES.charAt((b & 0x0F)));
        }
        log.info("客户端上报: " + hex.toString());
        // 字节数据转换为针对于808消息结构的实体类
        PackageData pkg = bytes2PackageData(req);
        out.add(pkg);
    }

    public PackageData bytes2PackageData(byte[] data) {
        try {
            data = JT808ProtocolUtils.doEscape4Receive(data,0,data.length);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("转义异常"+e.toString());
        }
        PackageData ret = new PackageData();

        // 0. 终端套接字地址信息
        // ret.setChannel(msg.getChannel());

        // 1. 16byte 或 12byte 消息头
        MsgHeader msgHeader = this.parseMsgHeaderFromBytes(data);
        ret.setMsgHeader(msgHeader);

        int msgBodyByteStartIndex = 12;
        // 2. 消息体
        // 有子包信息,消息体起始字节后移四个字节:消息包总数(word(16))+包序号(word(16))
        if (msgHeader.isHasSubPackage()) {
            msgBodyByteStartIndex = 16;
        }

        byte[] tmp = new byte[msgHeader.getMsgBodyLength()];
        System.arraycopy(data, msgBodyByteStartIndex, tmp, 0, tmp.length);
        ret.setMsgBodyBytes(tmp);

        // 3. 去掉分隔符之后，最后一位就是校验码
        // int checkSumInPkg =
        // this.bitOperator.oneByteToInteger(data[data.length - 1]);
        int checkSumInPkg = data[data.length - 1];
        int calculatedCheckSum = BitOperator.getCheckSum4JT808(data, 0, data.length - 1);
        ret.setCheckSum(checkSumInPkg);
        ret.setCalculatedCheckSum(calculatedCheckSum);
        if (checkSumInPkg != calculatedCheckSum) {
            log.warn("检验码不一致,msgid:{},pkg:{},calculated:{}", msgHeader.getMsgId(), checkSumInPkg, calculatedCheckSum);
        }
        return ret;
    }

    private MsgHeader parseMsgHeaderFromBytes(byte[] data) {
        MsgHeader msgHeader = new MsgHeader();

        // 1. 消息ID word(16)
        // byte[] tmp = new byte[2];
        // System.arraycopy(data, 0, tmp, 0, 2);
        // msgHeader.setMsgId(this.bitOperator.twoBytesToInteger(tmp));
        msgHeader.setMsgId(this.parseIntFromBytes(data, 0, 2));

        // 2. 消息体属性 word(16)=================>
        // System.arraycopy(data, 2, tmp, 0, 2);
        // int msgBodyProps = this.bitOperator.twoBytesToInteger(tmp);
        int msgBodyProps = this.parseIntFromBytes(data, 2, 2);
        msgHeader.setMsgBodyPropsField(msgBodyProps);
        // [ 0-9 ] 0000,0011,1111,1111(3FF)(消息体长度)
        msgHeader.setMsgBodyLength(msgBodyProps & 0x3ff);
        // [10-12] 0001,1100,0000,0000(1C00)(加密类型)
        msgHeader.setEncryptionType((msgBodyProps & 0x1c00) >> 10);
        // [ 13_ ] 0010,0000,0000,0000(2000)(是否有子包)
        msgHeader.setHasSubPackage(((msgBodyProps & 0x2000) >> 13) == 1);
        // [14-15] 1100,0000,0000,0000(C000)(保留位)
        msgHeader.setReservedBit(((msgBodyProps & 0xc000) >> 14) + "");
        // 消息体属性 word(16)<=================

        // 3. 终端手机号 bcd[6]
        // tmp = new byte[6];
        // System.arraycopy(data, 4, tmp, 0, 6);
        // msgHeader.setTerminalPhone(this.bcd8421Operater.bcd2String(tmp));
        msgHeader.setTerminalPhone(this.parseBcdStringFromBytes(data, 4, 6));

        // 4. 消息流水号 word(16) 按发送顺序从 0 开始循环累加
        // tmp = new byte[2];
        // System.arraycopy(data, 10, tmp, 0, 2);
        // msgHeader.setFlowId(this.bitOperator.twoBytesToInteger(tmp));
        msgHeader.setFlowId(this.parseIntFromBytes(data, 10, 2));

        // 5. 消息包封装项
        // 有子包信息
        if (msgHeader.isHasSubPackage()) {
            // 消息包封装项字段
            msgHeader.setPackageInfoField(this.parseIntFromBytes(data, 12, 4));
            // byte[0-1] 消息包总数(word(16))
            // tmp = new byte[2];
            // System.arraycopy(data, 12, tmp, 0, 2);
            // msgHeader.setTotalSubPackage(this.bitOperator.twoBytesToInteger(tmp));
            msgHeader.setTotalSubPackage(this.parseIntFromBytes(data, 12, 2));

            // byte[2-3] 包序号(word(16)) 从 1 开始
            // tmp = new byte[2];
            // System.arraycopy(data, 14, tmp, 0, 2);
            // msgHeader.setSubPackageSeq(this.bitOperator.twoBytesToInteger(tmp));
            msgHeader.setSubPackageSeq(this.parseIntFromBytes(data, 14, 2));
        }
        return msgHeader;
    }

    protected String parseStringFromBytes(byte[] data, int startIndex, int lenth) {
        return this.parseStringFromBytes(data, startIndex, lenth, null);
    }

    private String parseStringFromBytes(byte[] data, int startIndex, int lenth, String defaultVal) {
        try {
            byte[] tmp = new byte[lenth];
            System.arraycopy(data, startIndex, tmp, 0, lenth);
            return new String(tmp, TPMSConsts.string_charset);
        } catch (Exception e) {
            log.error("解析字符串出错:{}", e.getMessage());
            e.printStackTrace();
            return defaultVal;
        }
    }

    private String parseBcdStringFromBytes(byte[] data, int startIndex, int lenth) {
        return this.parseBcdStringFromBytes(data, startIndex, lenth, null);
    }

    private String parseBcdStringFromBytes(byte[] data, int startIndex, int lenth, String defaultVal) {
        try {
            byte[] tmp = new byte[lenth];
            System.arraycopy(data, startIndex, tmp, 0, lenth);
            return BCD8421Operater.bcd2String(tmp);
        } catch (Exception e) {
            log.error("解析BCD(8421码)出错:{}", e.getMessage());
            e.printStackTrace();
            return defaultVal;
        }
    }

    private int parseIntFromBytes(byte[] data, int startIndex, int length) {
        return this.parseIntFromBytes(data, startIndex, length, 0);
    }

    private int parseIntFromBytes(byte[] data, int startIndex, int length, int defaultVal) {
        try {
            // 字节数大于4,从起始索引开始向后处理4个字节,其余超出部分丢弃
            final int len = length > 4 ? 4 : length;
            byte[] tmp = new byte[len];
            System.arraycopy(data, startIndex, tmp, 0, len);
            return BitOperator.byteToInteger(tmp);
        } catch (Exception e) {
            log.error("解析整数出错:{}", e.getMessage());
            e.printStackTrace();
            return defaultVal;
        }
    }

    private Long parseLongFromBytes(byte[] data, int startIndex, int length) {
        return this.parseLongFromBytes(data, startIndex, length, 0L);
    }

    private Long parseLongFromBytes(byte[] data, int startIndex, int length, Long defaultVal) {
        try {
            // 字节数大于4,从起始索引开始向后处理4个字节,其余超出部分丢弃
            final int len = length > 4 ? 4 : length;
            byte[] tmp = new byte[len];
            System.arraycopy(data, startIndex, tmp, 0, len);
            return BitOperator.bytes2Long(tmp);
        } catch (Exception e) {
            log.error("解析整数出错:{}", e.getMessage());
            e.printStackTrace();
            return defaultVal;
        }
    }

    public TerminalCommonMsg toTerminalCommonMsg(PackageData packageData) {
        TerminalCommonMsg ret = new TerminalCommonMsg(packageData);
        byte[] data = ret.getMsgBodyBytes();
        TerminalCommonMsg.TerminalCommonInfo body = new TerminalCommonMsg.TerminalCommonInfo();

        // 应答流水号(WORD)
        body.setRespflowId(this.parseIntFromBytes(data, 0, 2));

        // 2. byte[2-3] 设备安装车辆所在的市域或县域,市县域ID采用GB/T2260中规定的行 政区划代码6位中后四位
        // 应答ID(WORD)
        body.setRespId(this.parseIntFromBytes(data, 2, 2));

        // 结果(BYTE) 0：成功/确认；1：失败；2：消息有误；3：不支持
        body.setResult(this.parseIntFromBytes(data, 4, 1));

        ret.setTerminalCommonInfo(body);
        return ret;
    }

    public TerminalRegisterMsg toTerminalRegisterMsg(PackageData packageData) {
        TerminalRegisterMsg ret = new TerminalRegisterMsg(packageData);
        byte[] data = ret.getMsgBodyBytes();

        TerminalRegisterMsg.TerminalRegInfo body = new TerminalRegisterMsg.TerminalRegInfo();

        // 1. byte[0-1] 省域ID(WORD)
        // 设备安装车辆所在的省域，省域ID采用GB/T2260中规定的行政区划代码6位中前两位
        // 0保留，由平台取默认值
        body.setProvinceId(this.parseIntFromBytes(data, 0, 2));

        // 2. byte[2-3] 设备安装车辆所在的市域或县域,市县域ID采用GB/T2260中规定的行 政区划代码6位中后四位
        // 0保留，由平台取默认值
        body.setCityId(this.parseIntFromBytes(data, 2, 2));

        // 3. byte[4-8] 制造商ID(BYTE[5]) 5 个字节，终端制造商编码
        // byte[] tmp = new byte[5];
        body.setManufacturerId(this.parseStringFromBytes(data, 4, 5));

        // 4. byte[9-29] 终端型号(BYTE[20]) 20个字节， 此终端型号 由制造商自行定义 位数不足20位的，补0X00。
        String terminalType = this.parseStringFromBytes(data, 9, 20);
        terminalType = terminalType.replace("\u0000", "");
        body.setTerminalType(terminalType);

        // 5. byte[29-36] 终端ID(BYTE[7]) 七个字节， 由大写字母 和数字组成， 此终端 ID由制造 商自行定义
        body.setTerminalId(this.parseStringFromBytes(data, 29, 7));

        // 6. byte[36] 车牌颜色(BYTE) 车牌颜 色按照JT/T415-2006 中5.4.12 的规定
        body.setLicensePlateColor(this.parseIntFromBytes(data, 36, 1));

        // 7. byte[37-x] 车牌(STRING) 公安交 通管理部门颁 发的机动车号牌
        String licensePlate = this.parseStringFromBytes(data, 37, data.length - 37);
        licensePlate = licensePlate.replace("\u0000", "");
        body.setLicensePlate(licensePlate);

        ret.setTerminalRegInfo(body);
        return ret;
    }


    public LocationInfoUploadMsg toLocationInfoUploadMsg(PackageData packageData) {
        LocationInfoUploadMsg ret = new LocationInfoUploadMsg(packageData);
        final byte[] data = ret.getMsgBodyBytes();
        // 1. byte[0-3] 报警标志(DWORD(32))
        byte[] ttt = new byte[4];
        System.arraycopy(data, 0, ttt, 0, 4);
        String warningFlagFieStr = "";
        for(byte byyy:ttt){
            warningFlagFieStr = warningFlagFieStr + ByteUtils.byteToBitString(byyy);
        }
        ret.setWarningFlagField(warningFlagFieStr);
        // 2. byte[4-7] 状态(DWORD(32))
        byte[] tmp = new byte[4];
        System.arraycopy(data, 4, tmp, 0, 4);
        String statusStr = "";
        for(byte byyy:tmp){
            statusStr = statusStr + ByteUtils.byteToBitString(byyy);
        }
        ret.setStatusField(statusStr);
        // 3. byte[8-11] 纬度(DWORD(32)) 以度为单位的纬度值乘以10^6，精确到百万分之一度
        ret.setLatitude(this.parseLongFromBytes(data, 8, 4));
        // 4. byte[12-15] 经度(DWORD(32)) 以度为单位的经度值乘以10^6，精确到百万分之一度
        ret.setLongitude(this.parseLongFromBytes(data, 12, 4));
        // 5. byte[16-17] 高程(WORD(16)) 海拔高度，单位为米（ m）
        ret.setElevation(this.parseIntFromBytes(data, 16, 2));
        // byte[18-19] 速度(WORD) 1/10km/h
        ret.setSpeed(this.parseLongFromBytes(data, 18, 2) / 10);
        // byte[20-21] 方向(WORD) 0-359，正北为 0，顺时针
        ret.setDirection(this.parseIntFromBytes(data, 20, 2));
        // byte[22-x] 时间(BCD[6]) YY-MM-DD-hh-mm-ss
        // GMT+8 时间，本标准中之后涉及的时间均采用此时区
        ret.setTrajectoryTime(this.parseBcdStringFromBytes(data, 22, 6));
        if(data.length > 28) {
            ret.setAddInfoId(String.valueOf(parseIntFromBytes(data, 28, 1)));
            ret.setAddInfo(parseStringFromBytes(data, 30, parseIntFromBytes(data, 29, 1)));
        }
        return ret;
    }

    public LocationInfoQueryMsg toLocationInfoQueryMsg(PackageData packageData) {
        LocationInfoQueryMsg ret = new LocationInfoQueryMsg(packageData);
        final byte[] data = ret.getMsgBodyBytes();
        // byte[0-1] 位置信息查询流水号
        ret.setMsgFlowId(this.parseIntFromBytes(data, 0, 2));
        // 1. byte[2-5]报警标志(DWORD(32))
        byte[] ttt = new byte[4];
        System.arraycopy(data, 2, ttt, 0, 4);
        String warningFlagFieStr = "";
        for(byte byyy:ttt){
            warningFlagFieStr = warningFlagFieStr + ByteUtils.byteToBitString(byyy);
        }
        ret.setWarningFlagField(warningFlagFieStr);
        // 2. byte[6-9] 状态(DWORD(32))
        byte[] tmp = new byte[4];
        System.arraycopy(data, 6, tmp, 0, 4);
        String statusStr = "";
        for(byte byyy:tmp){
            statusStr = statusStr + ByteUtils.byteToBitString(byyy);
        }
        ret.setStatusField(statusStr);
        // 3. bytee[10-13] 纬度(DWORD(32)) 以度为单位的纬度值乘以10^6，精确到百万分之一度
        ret.setLatitude(String.valueOf(this.parseLongFromBytes(data, 10, 4)));
        // 4. byte[14-17] 经度(DWORD(32)) 以度为单位的经度值乘以10^6，精确到百万分之一度
        ret.setLongitude(String.valueOf(this.parseLongFromBytes(data, 14, 4)));
        // 5. byte[18-19] 高程(WORD(16)) 海拔高度，单位为米（ m）
        ret.setElevation(this.parseIntFromBytes(data, 18, 2));
        // byte[20-21] 速度(WORD) 1/10km/h
        ret.setSpeed(String.valueOf(this.parseLongFromBytes(data, 20, 2) / 10));
        // byte[22-23] 方向(WORD) 0-359，正北为 0，顺时针
        ret.setDirection(this.parseIntFromBytes(data, 22, 2));
        // byte[24-x] 时间(BCD[6]) YY-MM-DD-hh-mm-ss
        // GMT+8 时间，本标准中之后涉及的时间均采用此时区
        ret.setTrajectoryTime(this.parseBcdStringFromBytes(data, 24, 6));
        if(data.length > 30) {
            ret.setAddInfoId(String.valueOf(parseIntFromBytes(data, 30, 1)));
            ret.setAddInfo(parseStringFromBytes(data, 32, parseIntFromBytes(data, 31, 1)));
        }
        return ret;
    }

    public PhotoScreenMsg toPhotoScreenMsg(PackageData packageData) {
        PhotoScreenMsg ret = new PhotoScreenMsg(packageData);
        final byte[] data = ret.getMsgBodyBytes();
        // byte[0-1] 应答流水号
        ret.setMsgFlowId(this.parseIntFromBytes(data, 0, 2));
        // byte[2] 结果
        ret.setResult(this.parseIntFromBytes(data, 2, 1));
        // byte[3] 多媒体ID个数
        ret.setMediaCount(this.parseIntFromBytes(data, 3, 1));
        // byte[4] 多媒体ID列表
        ret.setMediaList(this.parseIntFromBytes(data, 4, 1));
        return ret;
    }

    public MediaFileMsg toMediaFileMsg(PackageData packageData) {
        MediaFileMsg ret = new MediaFileMsg();
        final byte[] data = packageData.getMsgBodyBytes();
        // byte[0-3] 多媒体ID
        ret.setMediaFileId(this.parseLongFromBytes(data, 0, 4));
        // byte[4] 多媒体类型
        ret.setMediaType(this.parseIntFromBytes(data, 4, 1));
        // byte[5] 多媒体格式编码
        ret.setFormatCode(this.parseIntFromBytes(data, 5, 1));
        // byte[6] 事件项编码
        ret.setEventCode(this.parseIntFromBytes(data, 6, 1));
        // byte[7] 通道ID
        ret.setChnId(this.parseIntFromBytes(data, 7, 1));
        ret.setTerminalPhone(packageData.getMsgHeader().getTerminalPhone());
        byte[] file = new byte[data.length - 36];
        System.arraycopy(data, 36, file, 0, file.length);
        ret.setFile(file);
        return ret;
    }

    public HistoryVideoMsg toHistoryVideoMsg(PackageData packageData) {
        HistoryVideoMsg ret = new HistoryVideoMsg(packageData);
        String phone = packageData.getMsgHeader().getTerminalPhone();
        //byte[0-1]流水号
        final byte[] data = ret.getMsgBodyBytes();
        ret.setMsgFlowId(this.parseIntFromBytes(data, 0, 2));
        //byte[2-5]音视频资源总数
        int videoNum = this.parseIntFromBytes(data, 2, 4);
        ret.setVideoNum(videoNum);
        if(videoNum > 0){
            List<HistoryVideoMsg.Video> videoList = new ArrayList();
            byte[] file = new byte[data.length - 6];
            System.arraycopy(data, 6, file, 0, file.length);
            for(int i = 0;i<videoNum;i++){
                byte[] fileBuff = new byte[28];
                System.arraycopy(file, i*28, fileBuff, 0, fileBuff.length);
                HistoryVideoMsg.Video video = new HistoryVideoMsg.Video();
                // byte[0] 逻辑通道号
                video.setLogicalChn(this.parseIntFromBytes(fileBuff, 0, 1));
                // byte[1-6] 开始时间 (BCD(6))
                String beginTimeStr = this.parseBcdStringFromBytes(fileBuff, 1, 6);
                video.setBeginTime(beginTimeStr);
                try {
                    Date date = DateUtil.getDate(beginTimeStr,"yyMMddHHmmss");
                    video.setBeginDate(DateUtil.getDateStr(date,"yyyy-MM-dd"));
                    video.setBeginTimeFormat(DateUtil.getDateStr(date,"MM-dd HH:mm:ss"));
                } catch (ParseException e) {
                    e.printStackTrace();
                    log.error("日期转换错误：{}"+e.toString());
                }
                // byte[7-12] 结束时间 (BCD(6))
                String endTimeStr = this.parseBcdStringFromBytes(fileBuff, 7, 6);
                video.setEndTime(endTimeStr);
                try {
                    Date date = DateUtil.getDate(endTimeStr,"yyMMddHHmmss");
                    video.setEndDate(DateUtil.getDateStr(date,"yyyy-MM-dd"));
                    video.setEndTimeFormat(DateUtil.getDateStr(date,"MM-dd HH:mm:ss"));
                } catch (ParseException e) {
                    e.printStackTrace();
                    log.error("日期转换错误：{}"+e.toString());
                }
                video.setPhone(phone);
                // byte[13-20] 报警标志
                video.setWarningFlag(this.parseIntFromBytes(fileBuff, 13, 8));
                // byte[21] 音视频资源类型 0：音视频，1：音频，2：视频
                video.setResourceType(this.parseIntFromBytes(fileBuff, 21, 1));
                // byte[22] 码流类型 1：主码流，2：子码流
                video.setStreamType(this.parseIntFromBytes(fileBuff, 22, 1));
                // byte[23] 存储器类型 1：主存储器，2：灾备存储器
                video.setStorageType(this.parseIntFromBytes(fileBuff, 23, 1));
                // byte[24] 文件大小
                video.setFileSize(this.parseIntFromBytes(fileBuff, 24, 1));
                videoList.add(video);
            }
            ret.setVideoList(videoList);
        }
        return ret;
    }

    public ParamQueryMsg toParamQueryMsg(PackageData packageData) {
        ParamQueryMsg ret = new ParamQueryMsg(packageData);
        //byte[0-1]应答流水号
        final byte[] data = ret.getMsgBodyBytes();
        ret.setMsgFlowId(this.parseIntFromBytes(data, 0, 2));
        //byte[2-3]应答参数个数
        long paramNum = this.parseLongFromBytes(data, 2, 1);
        ret.setParamNum(paramNum);
        if(paramNum > 0){
            List<ParamQueryMsg.Param> paramList = new ArrayList();
            byte[] file = new byte[data.length - 3];
            System.arraycopy(data, 3, file, 0, file.length);
            int y = 0;
            for(int i = 0;i<paramNum;i++){
                ParamQueryMsg.Param param = new ParamQueryMsg.Param();
                int paramId = this.parseIntFromBytes(file, y, 4);
                param.setParamId(paramId);
                int paramLong = this.parseIntFromBytes(file,y+4,1);
                param.setParamLong(paramLong);
                String paramValue = "";
                if(paramId >= 0x0020  && paramId <= 0x0031 ){
                    paramValue = String.valueOf(this.parseIntFromBytes(file, y+4+1, paramLong));
                }
                if (paramId >= 0x0050  && paramId <= 0x0082 ){
                    paramValue = String.valueOf(this.parseIntFromBytes(file, y+4+1, paramLong));
                }
                if(paramId <= 0x0007||paramId == 0x0018||paramId == 0x0019||paramId ==0x001B||paramId ==0x001C){
                    paramValue = String.valueOf(this.parseIntFromBytes(file, y+4+1, paramLong));
                }
                if(paramId == 0x0045 ||paramId ==0x0046 ||paramId ==0x0047 ){
                    paramValue = String.valueOf(this.parseIntFromBytes(file, y+4+1, paramLong));
                }

                if (paramId == 0x001D|| paramId == 0x0048 || paramId == 0x0049 || paramId == 0x0083 ){
                    paramValue = this.parseStringFromBytes(file, y+4+1, paramLong);
                }
                if (paramId >= 0x0010 && paramId <= 0x0017){
                    paramValue = this.parseStringFromBytes(file, y+4+1, paramLong);
                }
                if (paramId >= 0x0040  && paramId <= 0x0044 ){
                    paramValue = this.parseStringFromBytes(file, y+4+1, paramLong);
                }

                param.setParamValue(paramValue);
                y = y + 4+1+ paramLong;
                paramList.add(param);
            }
            ret.setParamList(paramList);
        }
        return ret;
    }

    public VideoAttrMsg toVideoAttrMsg(PackageData packageData) {
        VideoAttrMsg ret = new VideoAttrMsg(packageData);
        final byte[] data = ret.getMsgBodyBytes();
        //byte[0]输入音频编码方式
        ret.setInputEncoding(this.parseIntFromBytes(data, 0, 1));
        //byte[1]输入音频声道数
        ret.setInputChannel(this.parseIntFromBytes(data, 1, 1));
        //byte[2]输入音频采样率
        ret.setInputRate(this.parseIntFromBytes(data, 2, 1));
        //byte[3]输入音频采样位数
        ret.setInputBits(this.parseIntFromBytes(data, 3, 1));
        //byte[4]音频帧长度
        ret.setFrameLength(this.parseIntFromBytes(data, 4, 2));
        //byte[6]是否支持音频输出
        ret.setIsEnableOutput(this.parseIntFromBytes(data, 6, 1));
        //byte[7]视频编码方式
        ret.setVideoEncoding(this.parseIntFromBytes(data, 7, 1));
        //byte[8]最大音频通道数
        ret.setMaxAudioChannels(this.parseIntFromBytes(data, 8, 1));
        //byte[9]最大视频通道数
        ret.setMaxVideoChannels(this.parseIntFromBytes(data, 9, 1));
        return ret;
    }

    private float parseFloatFromBytes(byte[] data, int startIndex, int length) {
        return this.parseFloatFromBytes(data, startIndex, length, 0f);
    }

    private float parseFloatFromBytes(byte[] data, int startIndex, int length, float defaultVal) {
        try {
            // 字节数大于4,从起始索引开始向后处理4个字节,其余超出部分丢弃
            final int len = length > 4 ? 4 : length;
            byte[] tmp = new byte[len];
            System.arraycopy(data, startIndex, tmp, 0, len);
            return BitOperator.byte2Float(tmp);
        } catch (Exception e) {
            log.error("解析浮点数出错:{}", e.getMessage());
            e.printStackTrace();
            return defaultVal;
        }
    }

}
